<template>
  <div>
    <comment-header v-if="postCount > 0" :comment-count="postCount" :is-positive-sort="isPositiveSort" @changeSort="changeSort" />
    <div v-else class="without-comment">{{ $t('topic.noComment') }}</div>
    <editor
      v-if="afterPushComment"
      editor-style="comment"
      class="comment-editor"
      selector="comment-editor"
      :type-information="commentType"
      :post.sync="comment"
      :on-publish="onCommentPublish"
      @publish="postCommentPublish"
    />
    <template v-if="postCount > 0">
      <div v-loading="commitLoading" style="min-height: 100px">
        <comment-list
          :thread-id="threadId"
          :comment-list="commentList"
          @replyPublish="updateSingleComment"
          @deleteComment="deleteComment"
          @deleteReply="deleteReply"
          @editComment="onEditComment"
          @like="onLike"
        />
      </div>
      <list-load-more
        :loading="scrollLoading"
        :length="commentList.length"
        :has-more="postCount > commentList.length"
        :page-num="pageNumber"
        @loadMore="getComment('scroll')"
      />
    </template>
    <el-dialog :title="$t('topic.editComment')" :visible="Object.keys(editComment).length > 0" width="820px" destroy-on-close @close="closeEditPop">
      <avatar-component :author="editComment.user || {}" :size="50">
        {{ $t('topic.publishAt') + ' ' + timerDiff(editComment.updatedAt) + $t('topic.before') }}..
      </avatar-component>
      <editor
        style="margin-top: 20px;"
        editor-style="comment"
        class="edit-comment-editor"
        selector="edit-comment-editor"
        :edit-resource-show="editResourceShow"
        :on-publish="onEditCommentPublish"
        :type-information="commentType"
        :post.sync="editCommentPost"
        :is-edit="true"
        @publish="postEditCommentPublish"
      />
    </el-dialog>
  </div>
</template>

<script>
const postInclude = 'user,replyUser,images,thread,user.groups,thread.category,thread.firstPost,lastThreeComments,lastThreeComments.user,lastThreeComments.replyUser,deletedUser,lastDeletedLog,lastThreeComments.images'
const commentInclude = 'user,likedUsers,commentPosts,commentPosts.user,commentPosts.user.groups,commentPosts.replyUser,commentPosts.replyUser.groups,commentPosts.mentionUsers,commentPosts.images,images,attachments'
import publishResource from '@/mixin/publishResource'
import postLegalityCheck from '@/mixin/postLegalityCheck'
import handleError from '@/mixin/handleError'
import timerDiff from '@/mixin/timerDiff'
import isLogin from '@/mixin/isLogin'
export default {
  name: 'Comment',
  mixins: [handleError, publishResource, postLegalityCheck, isLogin, timerDiff],
  props: {
    threadId: {
      type: String,
      default: '0'
    }
  },
  data() {
    return {
      commentList: [],
      postCount: 0,
      pageLimit: 5,
      pageNumber: 1,
      isPositiveSort: true,
      onCommentPublish: false,
      onEditCommentPublish: false,
      comment: { text: '', imageList: [], attachedList: [] },
      editResourceShow: { showUploadImg: false, showUploadVideo: false, showUploadAttached: false },
      editCommentPost: { text: '', imageList: [], attachedList: [] },
      editComment: {},
      commentType: { type: 10, textLimit: 5000, showPayment: false, showTitle: false, showImage: true, showVideo: false,
        showAttached: false, showEmoji: true, showTopic: false, showCaller: true, placeholder: '写下我的评论 ...' },
      commitLoading: false,
      scrollLoading: false,
      afterPushComment: true // 临时用了重置编辑器
    }
  },
  created() {
    this.getComment('scroll')
  },
  methods: {
    getComment(type) {
      if (this.commitLoading) return // 事件防抖
      type === 'commit' ? this.commitLoading = true : this.scrollLoading = true
      this.$store.dispatch('jv/get', [`posts`, { params: {
        'filter[thread]': this.threadId,
        'filter[isDeleted]': 'no',
        'filter[isComment]': 'no',
        'page[number]': this.pageNumber,
        'page[limit]': this.pageLimit,
        sort: this.isPositiveSort ? 'createdAt' : '-createdAt',
        include: postInclude
      }}]).then(data => {
        // TODO postCount 不包括审核中的回复
        this.pageNumber += 1
        this.commentList.push(...data)
        this.postCount = data.length > 0 ? (data[0].thread.postCount - 1) : 0
      }, e => this.handleError(e)).finally(() => { this.commitLoading = this.scrollLoading = false })
    },
    updateSingleComment(commentId) {
      if (this.commitLoading === true) return // 事件防抖
      this.commitLoading = true
      return this.$store.dispatch('jv/get', [`posts/${commentId}`, { params: { include: commentInclude }}]).then(comment => {
        comment.lastThreeComments = comment.commentPosts.reverse().filter(item => !item.isDeleted).slice(0, 3) // 除去已删除，改为倒叙，截取前三
        this.$set(this.commentList, this.getCommentIndexFromId(commentId), comment)
        this.commitLoading = false
      }, e => this.handleError(e)).finally(() => { this.commitLoading = false })
    },
    changeSort(value) {
      this.scrollLoading = true
      this.pageNumber = 1
      this.commentList = []
      this.isPositiveSort = value
      this.getComment('commit')
    },
    onLike({ comment, index }) {
      const params = {
        _jv: { type: `posts`, id: comment._jv.id },
        isLiked: !comment.isLiked,
        include: postInclude
      }
      return this.$store.dispatch('jv/patch', params).then(data => {
        this.$set(this.commentList, index, data)
      }, e => this.handleError(e))
    },
    deleteComment(id) {
      const params = { _jv: { type: `posts`, id }, isDeleted: true }
      this.$confirm(this.$t('topic.confirmDelete'), this.$t('discuzq.msgBox.title'), {
        confirmButtonText: this.$t('discuzq.msgBox.confirm'),
        cancelButtonText: this.$t('discuzq.msgBox.cancel'),
        type: 'warning'
      }).then(() => {
        return this.$store.dispatch('jv/patch', params).then(() => {
          this.postCount -= 1
          this.commentList.splice(this.getCommentIndexFromId(id), 1)
          this.$message.success(this.$t('topic.deleteSuccess'))
        }, e => this.handleError(e))
      }, () => console.log('取消删除'))
    },
    deleteReply({ replyId, commentId }) {
      const params = {
        _jv: { type: `posts`, id: replyId },
        isDeleted: true
      }
      this.$confirm(this.$t('topic.confirmDelete'), this.$t('discuzq.msgBox.title'), {
        confirmButtonText: this.$t('discuzq.msgBox.confirm'),
        cancelButtonText: this.$t('discuzq.msgBox.cancel'),
        type: 'warning'
      }).then(() => {
        return this.$store.dispatch('jv/patch', params).then(() => {
          this.updateSingleComment(commentId)
          this.$message.success(this.$t('topic.deleteSuccess'))
        }, e => this.handleError(e))
      }, () => console.log('取消删除'))
    },
    onEditComment(comment) {
      this.editComment = comment
      this.editCommentPost.text = comment.content
      this.$nextTick(() => {
        const textarea = document.querySelector(`.edit-comment-editor #textarea`)
        textarea.style.height = textarea.scrollHeight + 'px' // TODO 重置textarea 待优
      })
      if (comment.images.length > 0) {
        this.initThreadResource(this.editCommentPost.imageList, comment.images)
        this.editResourceShow.showUploadImg = true
      }
    },
    postEditCommentPublish() {
      if (!this.isLogin()) return
      if (this.onEditCommentPublish) return
      if (!this.editCommentPost.text) return this.$message.warning(this.$t('post.theContentCanNotBeBlank'))
      if (this.editCommentPost.text.length > this.commentType.textLimit) return this.$message.warning(this.$t('post.messageLengthCannotOver'))
      this.onEditCommentPublish = true
      let editCommentParams = {
        _jv: {
          type: `posts`,
          relationships: {}
        },
        content: this.editCommentPost.text
      }
      if (this.threadId) editCommentParams._jv.id = this.threadId
      editCommentParams = this.publishPostResource(editCommentParams, this.editCommentPost)
      this.deleteAttachmentsAfterEdit(this.editComment.images, this.editCommentPost.imageList)
      this.$store.dispatch('jv/patch', [editCommentParams, { url: `/posts/${this.editComment._jv.id}` }]).then(response => {
        this.updateSingleComment(this.editComment._jv.id)
        this.postLegalityCheck(response, this.$t('topic.commentPublishSuccess'))
        this.closeEditPop()
      }, e => this.handleError(e)).finally(() => { this.onEditCommentPublish = false })
    },
    closeEditPop() {
      this.editComment = {}
      this.editCommentPost.text = ''
      this.editCommentPost.imageList = []
      this.editResourceShow.showUploadImg = false
    },
    initThreadResource(target, resource) {
      resource.forEach(item => {
        const attached = {
          name: item.fileName,
          url: item.thumbUrl,
          id: item._jv.id,
          deleted: false // 用于图片 upload 的样式
        }
        target.push(attached)
      })
    },
    postCommentPublish() {
      if (!this.isLogin()) return
      if (this.onCommentPublish) return
      if (!this.comment.text) return this.$message.warning(this.$t('post.theContentCanNotBeBlank'))
      if (this.comment.text.length > this.commentType.textLimit) return this.$message.warning(this.$t('post.messageLengthCannotOver'))
      this.onCommentPublish = true
      const commentParams = {
        _jv: {
          type: `posts`,
          relationships: {
            thread: { data: { type: 'threads', id: this.threadId }}
          }
        },
        content: this.comment.text
      }
      this.publishPostResource(commentParams, this.comment)
      return this.$store.dispatch('jv/post', commentParams).then(response => {
        this.comment.text = ''
        this.comment.imageList = []
        this.afterPushComment = false // 重置输入框
        this.$nextTick(() => { this.afterPushComment = true })
        this.postLegalityCheck(response, this.$t('topic.commentPublishSuccess'))
        // false 倒序 true 正序， 倒叙是从最新到最旧
        if (this.isPositiveSort) {
          this.commentList.length === this.postCount ? this.commentList.push(response) : ''
        } else {
          this.commentList.unshift(response)
        }
        this.postCount += 1
      }, e => this.handleError(e)).finally(() => { this.onCommentPublish = false })
    },
    getCommentIndexFromId(id) {
      const deleteComment = this.commentList.filter(item => item._jv.id === id)[0]
      return this.commentList.indexOf(deleteComment)
    }
  }
}
</script>

<style>
.el-dialog {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  margin: 0 !important;
}
.el-dialog .el-dialog__body {
  padding: 20px;
}
.el-dialog .el-dialog__title {
  color: #6d6d6d;
  font-size: 16px;
  font-weight: 700;
}
.el-dialog .el-dialog__header {
  padding-bottom: 0;
}
.el-dialog .el-icon-close {
  font-size: 22px;
}
</style>

<style lang="scss" scoped>
  @import '@/assets/css/variable/color.scss';

  .container-show-more {
    padding-top: 20px;
    border-top: 1px solid $border-color-base;
    .show-more {
      width: 100%;
      border: 1px solid $color-blue-base;
      border-radius: 3px;
      font-size: 16px;
      height: 45px;
      line-height: 45px;
      color: $color-blue-base;
    }
  }
  .without-comment {
    color: $font-color-grey;
    text-align: center;
  }
  .edit-box {
    padding: 20px;
  }

</style>
